﻿using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Cors.Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;

namespace Jy.Abp.AspNetCore.Cors;

/*
  想要覆盖之前的ICorsService,需要在AddMvc()之后，替换,例如下：
  services.Add(ServiceDescriptor.Transient<ICorsService, WildcardCorsService>());
  services.Configure<CorsOptions>(options => options.AddPolicy(
  "AllowSameDomain",
  builder => builder.WithOrigins("*.test.com")));
   */
/// <summary>
/// 自定义跨域处理服务，增加通配符二级域名策略  ICorsService
/// </summary>
[Dependency(ReplaceServices = true)]
public class WildcardCorsService : CorsService, ICorsService, ITransientDependency
{
    public WildcardCorsService(IOptions<CorsOptions> options, ILoggerFactory loggerFactory)
        : base(options, loggerFactory)
    {

    }

    #region 在默认处理域名策略之前，提前拦截,用自己的策略

    public override void EvaluateRequest(HttpContext context, CorsPolicy policy, CorsResult result)
    {
        var origin = context.Request.Headers[CorsConstants.Origin];
        //拦截
        //Orings为策略(*.test.com)(该策略可多个)    origin为跨域请求的域名
        EvaluateOriginForWildcard(policy.Origins, origin);
        //策略根据通配符替换完成
        base.EvaluateRequest(context, policy, result);
    }

    public override void ApplyResult(CorsResult result, HttpResponse response)
    {
        base.ApplyResult(result, response);
    }

    public override void EvaluatePreflightRequest(HttpContext context, CorsPolicy policy, CorsResult result)
    {
        var origin = context.Request.Headers[CorsConstants.Origin];
        //拦截
        EvaluateOriginForWildcard(policy.Origins, origin);
        //策略根据通配符替换完成
        base.EvaluatePreflightRequest(context, policy, result);
    }
    #endregion
    private void EvaluateOriginForWildcard(IList<string> origins, string origin)
    {
        //只在没有匹配的origin的情况下进行操作
        if (!origins.Contains(origin))
        {
            if (origins.Any(wildcardDomain => Regex.IsMatch(origin, wildcardDomain)))
                origins.Add(origin);
        }
    }
}
